/** 
 * ====================================================================
 * takephoto.cpp
 *
 * Modified from "miso" (HIIT) and video example available Forum Nokia.
 *
 * Copyright 2005 Helsinki Institute for Information Technology (HIIT)
 * and the authors.  All rights reserved.
 * Authors: Tero Hasu <tero.hasu@hut.fi>
 *
 * Portions Copyright (c) 2005-2008 Nokia Corporation 
 * 
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation files
 * (the "Software"), to deal in the Software without restriction,
 * including without limitation the rights to use, copy, modify, merge,
 * publish, distribute, sublicense, and/or sell copies of the Software,
 * and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 * ====================================================================
 */

#include "cameramodule.h"

//Alex: added logging.
#include "common/logging.h"


extern CAM_object *camo;

// A helper function for the implementation of callbacks
// from C/C++ code to Python callables (modified from appuifwmodule.cpp)
TInt TPyCamCallBack::NewViewFinderFrameReady(CFbsBitmap* aFrame)
  {
  PyGILState_STATE gstate = PyGILState_Ensure();

  TInt error = KErrNone;

  PyObject* bmp = PyCObject_FromVoidPtr(aFrame, NULL);
  PyObject* arg = Py_BuildValue("(O)", bmp);
  PyObject* rval = PyEval_CallObject(iCb, arg);
  
  Py_DECREF(arg);
  Py_DECREF(bmp);
  if (!rval) {
    error = KErrPython;
    if (PyErr_Occurred() == PyExc_OSError) {
      PyObject *type, *value, *traceback;
      PyErr_Fetch(&type, &value, &traceback);
      if (PyInt_Check(value))
        error = PyInt_AS_LONG(value);
      Py_XDECREF(type);
      Py_XDECREF(value);
      Py_XDECREF(traceback);
    } else {
      PyErr_Print();
    }
  }
  else
    Py_DECREF(rval);  

  PyGILState_Release(gstate);
  return error;
  }

//////////////////////////////////////////////

CMisoPhotoTaker* CMisoPhotoTaker::NewL(TInt aPosition)
{
  CMisoPhotoTaker* taker = new (ELeave) CMisoPhotoTaker;
  CleanupStack::PushL(taker);
  taker->iPosition = aPosition;
  taker->ConstructL();
  CleanupStack::Pop();
  return taker;
}

CMisoPhotoTaker::CMisoPhotoTaker()
{
  iStatus = KErrNone;
  iTakingPhoto = EFalse;
  iViewFinderStatus = EFinderInactive;
  iViewFinderSize = TSize();
}

void CMisoPhotoTaker::ConstructL()
{
  log_text("Entered CMisoPhotoTaker::ConstructL().");
  if (!CCamera::CamerasAvailable())
    User::Leave(KErrHardwareNotAvailable);
  
  iLoop = new (ELeave) CActiveSchedulerWait();

  //From http://www.developer.nokia.com/Community/Discussion/showthread.php?142251-Any-idea-on-CCameraAdvancedSettings-availability&p=463597: "To get you past the current problem please note that you need to implement the MCameraObserver2 interface and construct the camera using the CCamera::New2L() constructor."
  //Inspired from the fastcamera PyS60 module.
  #ifdef USE_NEW_CAMERA_API
    TRAPD(error, iCamera = CCamera::New2L(*this, iPosition, 0)); //From http://library.developer.nokia.com/index.jsp?topic=/GUID-E35887BB-7E58-438C-AA27-97B2CDE7E069/GUID-251A35C1-CC66-4DE4-9EBE-964026E89E7F/GUID-021C509B-C821-3401-B2F4-DE7F52BB16D4.html: aPriority Value from -100 to 100 indicating relative priority of client to use camera. 
    logf("CMisoPhotoTaker::ConstructL(): error = %d, iCamera = %x.", error, iCamera);
    if (error != KErrNone) {
        log_text("CMisoPhotoTaker::ConstructL(): error when trying to use CCamera::New2L() --> using CCamera::NewL() instead.");
        iCamera = CCamera::NewL(*this, iPosition);
        //useNewFocus = EFalse;
    }
  #else
    iCamera = CCamera::NewL(*this, iPosition);
  #endif

  iCamera->CameraInfo(iInfo);
}

CMisoPhotoTaker::~CMisoPhotoTaker()
{
  if (iCamera) {
    // assuming this is safe even if not on
    iCamera->PowerOff();
    // assuming safe even if not reserved
    iCamera->Release();
    delete iCamera;
  }
  delete iLoop;
}

void CMisoPhotoTaker::SetCameraParameters(TInt aMode, TInt aSize, 
                                        TInt aZoom, TInt aFlash, 
                                        TInt aExp, TInt aWhite, TInt aISORate) {
    //Alex: TInt aShutterSpeed, TInt aExposureCompensation (or maybe aExposureaCompensationStep), TInt aFocusRangeIndex
    iMode = static_cast<CCamera::TFormat>(aMode);
    iSize = aSize;
    iZoom = aZoom;
    iFlash = static_cast<CCamera::TFlash>(aFlash);
    iExp = static_cast<CCamera::TExposure>(aExp);
    iWhite = static_cast<CCamera::TWhiteBalance>(aWhite);
    ISORate = aISORate;
    
}

void CMisoPhotoTaker::TakePhotoL(TInt aMode, TInt aSizeIndex, 
                                        TInt aZoom, TInt aFlash, 
                                        TInt aExp, TInt aWhite)
{
  iTakingPhoto = ETrue;

  SetCameraParameters(aMode, aSizeIndex, aZoom, aFlash, aExp, aWhite, -100);

  MakeTakePhotoRequest(); //iCamera->Reserve() asynchronously calls CMisoPhotoTaker::ReserveComplete.
  // Start the wait for reserve complete, this ends after the completion
  // of ImageReady
  iLoop->Start();

  iTakingPhoto = EFalse;
  User::LeaveIfError(iStatus);
}

void CMisoPhotoTaker::StartViewFinder(TInt aXSize, TInt aYSize) {
  iViewFinderSize.SetSize(aXSize, aYSize);
  // TODO Check if we are taking photo already will be needed when
  // there is Python "Camera" type
  iViewFinderStatus = EFinderInitializing;
  iCamera->Reserve();
  iLoop->Start();
}

void CMisoPhotoTaker::StopViewFinder() {
    if(iViewFinderStatus == EFinderActive){
      iCamera->StopViewFinder();
      iCamera->PowerOff();
      iCamera->Release();
    }
    iViewFinderStatus = EFinderInactive;
}

void CMisoPhotoTaker::SetCallBack(TPyCamCallBack &aCb) {
    iCallMe = aCb;
    iCallBackSet = ETrue;
}

void CMisoPhotoTaker::UnSetCallBack() {
    iCallBackSet = EFalse;
}

void CMisoPhotoTaker::Release() const {
    iCamera->Release();
}

TBool CMisoPhotoTaker::TakingPhoto() const {
    return iTakingPhoto;
}

TBool CMisoPhotoTaker::ViewFinderOn() const {
    if (iViewFinderStatus == EFinderInactive)
        return EFalse;
    else
        return ETrue;
}

TInt CMisoPhotoTaker::GetVideoFormats() const // New!
{
    /*See http://library.forum.nokia.com/index.jsp?topic=/GUID-E35887BB-7E58-438C-AA27-97B2CDE7E069/GUID-251A35C1-CC66-4DE4-9EBE-964026E89E7F/GUID-644E96EC-EFDC-335D-B2B6-A1BDB8538C0A.html
    "The supported video frame formats.
    This is a bitfield of video frame CCamera::TFormat values."
    */
    return iInfo.iVideoFrameFormatsSupported;
}

void CMisoPhotoTaker::GetVideoFrameSize(TSize& aSize, TInt aSizeIndex, CCamera::TFormat aFormat) const // New!
{
    /*
     * From http://library.forum.nokia.com/index.jsp?topic=/GUID-E35887BB-7E58-438C-AA27-97B2CDE7E069/GUID-251A35C1-CC66-4DE4-9EBE-964026E89E7F/GUID-021C509B-C821-3401-B2F4-DE7F52BB16D4.html
     * void EnumerateVideoFrameSizes(TSize &aSize,
     *     TInt aSizeIndex,
     *     TFormat  aFormat
     * )    const [pure virtual]
     * 
     *   aSize  On return the available video frame sizes. Sizes should be returned in order, largest first, so clients do not have to iterate through every one.
     *   aSizeIndex Size index. Must be in the range 0 to TCameraInfo::iNumVideoFrameSizesSupported-1 inclusive
     *   aFormat    Image format. 
     */

    iCamera->EnumerateVideoFrameSizes(aSize, aSizeIndex, aFormat);
}

TInt CMisoPhotoTaker::GetNumVideoFrameSizesSupported() const // New!
{
  return iInfo.iNumVideoFrameSizesSupported;
}

// Added by AltoRetrato. Modified by Alex Susu. 
TReal32 CMisoPhotoTaker::GetVideoFrameRate(TInt aRateIndex, CCamera::TFormat aFormat, TInt aSizeIndex, CCamera::TExposure aExposure) const {
    TReal32 aRate;
    /*
    From http://library.forum.nokia.com/index.jsp?topic=/S60_3rd_Edition_Cpp_Developers_Library/GUID-35228542-8C95-4849-A73F-2B4F082F0C44/html/SDL_93/doc_source/reference/reference-cpp/ECAM/CCameraClass.html
        EnumerateVideoFrameRates()
            virtual void EnumerateVideoFrameRates(TReal32 &aRate, TInt aRateIndex, TFormat aFormat, TInt aSizeIndex, TExposure aExposure=EExposureAuto) const=0;
            Description
            Enumerates through the available video frame rates, based on the specified rate index, video frame format, size index and exposure mode.
            Parameters
              TReal32 &aRate - On return, the available video frame rates. Some rates may not be available due to, for example, current flash mode setting. In those cases a rate of 0 will be returned. Rates should be returned in order, highest first, so clients do not have to iterate through every one.
              TInt aRateIndex - The rate index. Must be in the range 0 to TCameraInfo::iNumVideoFrameRatesSupported-1 inclusive.
              TFormat aFormat - The format.
              TInt aSizeIndex - The size index.
              TExposure aExposure - The exposure mode.

        PrepareVideoCaptureL()
            virtual void PrepareVideoCaptureL(TFormat aFormat, TInt aSizeIndex, TInt aRateIndex, TInt aBuffersToUse, TInt aFramesPerBuffer)=0;
                TInt aRateIndex     
                The rate must be in the range 0 to TCameraInfo::iNumVideoFrameRatesSupported-1 inclusive. 
    */
    iCamera->EnumerateVideoFrameRates(aRate, aRateIndex, aFormat, aSizeIndex, aExposure);
    return aRate;
}

TReal32 CMisoPhotoTaker::GetNumVideoFrameRatesSupported() const // New!
{
  return iInfo.iNumVideoFrameRatesSupported;
}

TInt CMisoPhotoTaker::GetImageModes() const
{
  return iInfo.iImageFormatsSupported;
}

TInt CMisoPhotoTaker::GetImageSizeMax() const
{
  return iInfo.iNumImageSizesSupported;
}

void CMisoPhotoTaker::GetImageSize(TSize& aSize, TInt aSizeIndex, CCamera::TFormat aFormat) const
{
  iCamera->EnumerateCaptureSizes(aSize, aSizeIndex, aFormat);
}

TInt CMisoPhotoTaker::GetMaxZoom() const
{
  return iInfo.iMaxDigitalZoom;
}

TInt CMisoPhotoTaker::GetFlashModes() const
{
  return iInfo.iFlashModesSupported;
}

TInt CMisoPhotoTaker::GetExpModes() const
{
  return iInfo.iExposureModesSupported;
}

TInt CMisoPhotoTaker::GetWhiteModes() const
{
  return iInfo.iWhiteBalanceModesSupported;
}

TInt CMisoPhotoTaker::GetHandle() const
{
  return iCamera->Handle();
}

CFbsBitmap* CMisoPhotoTaker::GetBitmap() const
{
  CFbsBitmap* ret = iBitMap;
  return ret;
}

HBufC8* CMisoPhotoTaker::GetJpg() const
{
  HBufC8* ret = iData;
  return ret;
}

void CMisoPhotoTaker::MakeTakePhotoRequest()
{
  /* From http://library.developer.nokia.com/index.jsp?topic=/GUID-E35887BB-7E58-438C-AA27-97B2CDE7E069/GUID-251A35C1-CC66-4DE4-9EBE-964026E89E7F/GUID-021C509B-C821-3401-B2F4-DE7F52BB16D4.html:
   * Asynchronous function that performs any required initialisation and reserves the camera for exclusive use.
   * Calls MCameraObserver:: ReserveComplete() when complete.
   */
    iCamera->Reserve();
}

void CMisoPhotoTaker::CapturePhoto()
{
  // the settings, notice that these can be only set here,
  // i.e. in camera state MCameraObserver::PowerOnComplete()
  TRAPD(aError, SetCameraSettingsL());
  if (aError) {
    iStatus = aError;
    iLoop->AsyncStop();
  } else  {
    TRAP(aError, iCamera->PrepareImageCaptureL(
      iMode, iSize));
    /* From http://library.developer.nokia.com/index.jsp?topic=/GUID-E35887BB-7E58-438C-AA27-97B2CDE7E069/GUID-251A35C1-CC66-4DE4-9EBE-964026E89E7F/GUID-021C509B-C821-3401-B2F4-DE7F52BB16D4.html:
     * Performs setup and allocation of memory. 
     * Called prior to calling CaptureImage() to keep the latency of that function to a minimum.
     * Needs to be called only once for multiple CaptureImage() calls. May leave with KErrNotSupported or KErrNoMemory or KErrInUse or KErrNotReady.
     * The specified image format must be one of the formats supported (see TCameraInfo::iImageFormatsSupported).
     * The specified size index must be in the range of 0 to TCameraInfo::iNumImageSizesSupported-1 inclusive.
     * Note:
     * Depending on the ECAM implementation and underlying hardware, preparing both image capture and video capture at the same time may not be possible. In this case, the recommendation is to unprepare video capture before preparing image capture if PrepareVideoCaptureL() has already been called.
     * See also: CCamera::CCameraPreImageCaptureControl::PrepareImageCapture(TPrepareImageParameters aPrepareImageParameters) 
     */
    if (aError) {
      iStatus = aError;
      iLoop->AsyncStop();
    } else {
      // completes with ImageReady
      /* From http://library.developer.nokia.com/index.jsp?topic=/GUID-E35887BB-7E58-438C-AA27-97B2CDE7E069/GUID-251A35C1-CC66-4DE4-9EBE-964026E89E7F/GUID-021C509B-C821-3401-B2F4-DE7F52BB16D4.html:
       * Asynchronously performs still image capture.
       * Calls MCameraObserver::ImageReady() when complete.
       */ 
        iCamera->CaptureImage();
    }
  }
}

/*
// Returns highest color mode supported by HW
CCamera::TFormat CMisoPhotoTaker::ImageFormatMax() const
{
  if ( iInfo.iImageFormatsSupported & CCamera::EFormatFbsBitmapColor16M )
    {
    return CCamera::EFormatFbsBitmapColor16M;
    }
  else if ( iInfo.iImageFormatsSupported & CCamera::EFormatFbsBitmapColor64K )
    {
    return CCamera::EFormatFbsBitmapColor64K;
    }
  else 
    {
    return CCamera::EFormatFbsBitmapColor4K;
    }
}
*/

#ifdef S60_3rd_edition_FP2_onwards    
    #include "ecamadvsettings.h"
#endif
void CMisoPhotoTaker::SetCameraSettingsL() {
    log_text("Entered CMisoPhotoTaker::SetCameraSettingsL().");

    // The parameters need to be checked prior invoking the 
    // methods since otherwise a panic may occur (and not leave)
    if ((iZoom < 0) || (iZoom > iInfo.iMaxDigitalZoom))
      User::Leave(KErrNotSupported);
    else
      iCamera->SetDigitalZoomFactorL(iZoom);
  
    log_text("CMisoPhotoTaker::SetCameraSettingsL(): just set the digital zoom.");

    if ((iFlash & iInfo.iFlashModesSupported) || (iFlash == CCamera::EFlashNone))
    iCamera->SetFlashL(iFlash);
  else
    User::Leave(KErrNotSupported);
  
  if ((iExp & iInfo.iExposureModesSupported) || (iExp == CCamera::EExposureAuto))
    iCamera->SetExposureL(iExp);
  else
    User::Leave(KErrNotSupported);
  
  if ((iWhite & iInfo.iWhiteBalanceModesSupported) || (iWhite == CCamera::EWBAuto))
    iCamera->SetWhiteBalanceL(iWhite);
  else
    User::Leave(KErrNotSupported);

  log_text("CMisoPhotoTaker::SetCameraSettingsL(): finished call to iCamera->SetWhiteBalanceL().");

  //CCamera reference - see http://library.forum.nokia.com/index.jsp?topic=/S60_3rd_Edition_Cpp_Developers_Library/GUID-35228542-8C95-4849-A73F-2B4F082F0C44/html/SDL_93/doc_source/reference/reference-cpp/ECAM/CCameraClass.html
  //CVideoRecorderUtility Class Reference - see http://library.forum.nokia.com/index.jsp?topic=/S60_3rd_Edition_Cpp_Developers_Library/GUID-35228542-8C95-4849-A73F-2B4F082F0C44/html/SDL_93/doc_source/reference/reference-cpp/MMF/CVideoRecorderUtilityClass.html
  #ifdef S60_3rd_edition_FP2_onwards    
      //CCamera* iCamera;
      //From http://wiki.forum.nokia.com/index.php/Symbian_Onboard_Camera_Advanced_Settings_API - "On S60 platform, CCameraAdvancedSettings is supported from S60 3rd Edition, Feature Pack 2 onwards.":
  
      //From http://discussion.forum.nokia.com/forum/showthread.php?143268-How-to-disable-AF-of-camera: "If you had, you would have found that there is an example here: http://www.forum.nokia.com/main/reso...documents.html Called S60 Platform: Camera Example with AutoFocus Support. This uses an earlier library for autofocus support. Nokia did this first on their own and don't start using the new CCameraAdvancedSettings for autofocus until 3rd FP2, so your devices, using 3rd FP1 will still use the old library (it's in the example package before you ask where to get it!)."  
      /*
      Alex: in C:\Symbian\9.2\S60_3rd_FP1\Epoc32\include\ecam.h the class CCameraAdvancedSettings is declared but not defined/implemented - no methods, etc (also C:\Symbian\9.2\S60_3rd_FP1\Epoc32\release\armv5\lib\ecam*.dso and ecam*.lib don't contain anything).
      Note that N82 (S60 3rd FP1) (and probably N95 as well) have the S60 Camera app with ISO, eV. So, even if they are not in the SDK I guess these ISO, eV handling functions can be used with S60 3rd FP2 SDK.
       * Doesn't work until S60 3rd edition FP1 - see http://wiki.forum.nokia.com/index.php/KIS000498_-_Class_CCameraAdvancedSettings_is_documented_but_not_implemented: 
       * "CCameraAdvancedSettings is implemented from S60 3rd Edition, Feature Pack 2 onwards."
       * Also see http://wiki.forum.nokia.com/index.php/Symbian_Onboard_Camera_Advanced_Settings_API .
       * But it seems the CCameraAdvancedSettings is also on N95, N82 - see http://discussion.forum.nokia.com/forum/showthread.php?143268-How-to-disable-AF-of-camera: "N95.(N82?) ecamadvsettings.dll is exist.(It can be loaded by RLibrary).I try to use Camera::CCameraAdvancedSettings::NewL(). Leave with KErrNotSupported(-5). By the way, I get ecamadvsettings.h and ecamadvsettings.lib from UIQ sdk."
       */

      CCamera::CCameraAdvancedSettings *iAdvancedSettings = NULL;
      TInt err = 0;
      
      TRAP(err, iAdvancedSettings = CCamera::CCameraAdvancedSettings::NewL(*iCamera)); 
      if ( err || (iAdvancedSettings == NULL)) {
          logf("CMisoPhotoTaker::SetCameraSettingsL(): Because err = %d and iAdvancedSettings = %d we are bailing out.", err, iAdvancedSettings);
         return;
      }

      int index;

      /*
      IMPORT_C void GetSupportedIsoRatesL(RArray< TInt > &aSupportedIsoRates) const; - Gets the set of camera supported ISO rates.
      aSupportedIsoRates = an array of integers which gets filled with the supported ISO rates.
      */
      //iAdvancedSettings.CameraIndex();
      //RArray class reference: http://library.developer.nokia.com/index.jsp?topic=/GUID-E35887BB-7E58-438C-AA27-97B2CDE7E069/GUID-251A35C1-CC66-4DE4-9EBE-964026E89E7F/GUID-FAEBF321-6B08-3041-A01F-B1E7282D0707.html
      RArray<TInt> supportedIsoRates;
      iAdvancedSettings->GetSupportedIsoRatesL(supportedIsoRates);
      TInt lenSupportedIsoRates = supportedIsoRates.Count();
      //logf("CMisoPhotoTaker::SetCameraSettingsL(): lenSupportedIsoRates = %d, supportedIsoRates[0] = %d, supportedIsoRates[lenSupportedIsoRates - 1] = %d.", lenSupportedIsoRates, supportedIsoRates[0], supportedIsoRates[lenSupportedIsoRates - 1]); //supportedIsoRates.At(0), supportedIsoRates.At(lenSupportedIsoRates - 1));
      logf("CMisoPhotoTaker::SetCameraSettingsL(): lenSupportedIsoRates = %d.", lenSupportedIsoRates);
      for (index = 0; index < lenSupportedIsoRates; index++)
          logf("    supportedIsoRates[%d] = %d", index, supportedIsoRates[index]);
      supportedIsoRates.Close();
      
      /* From http://library.forum.nokia.com/index.jsp?topic=/GUID-E35887BB-7E58-438C-AA27-97B2CDE7E069/GUID-251A35C1-CC66-4DE4-9EBE-964026E89E7F/GUID-E31AEB11-B7A0-3637-BB31-866306F78118.html
       * IMPORT_C void GetShutterSpeedsL(RArray<TInt> &aShutterSpeeds, TValueInfo &aInfo) const
       * aShutterSpeeds a reference to an RArray of TInt representing the discrete shutter speeds supported currently by the camera.
       * aInfo  a reference to TValueInfo, which establishes the type of the returned data. 
       * Returns: the populated array with all shutter speeds in microseconds.
      */ 
      RArray<TInt> shutterSpeeds;
      TValueInfo shutterSpeedsInfo;
      iAdvancedSettings->GetShutterSpeedsL(shutterSpeeds, shutterSpeedsInfo);
      TInt lenShutterSpeeds = shutterSpeeds.Count();
      logf("CMisoPhotoTaker::SetCameraSettingsL(): lenShutterSpeeds = %d.", lenShutterSpeeds);
      for (index = 0; index < lenShutterSpeeds; index++)
          logf("    shutterSpeeds[%d] = %d", index, shutterSpeeds[index]);
      shutterSpeeds.Close();
      
      /* From http://library.forum.nokia.com/index.jsp?topic=/GUID-E35887BB-7E58-438C-AA27-97B2CDE7E069/GUID-251A35C1-CC66-4DE4-9EBE-964026E89E7F/GUID-E31AEB11-B7A0-3637-BB31-866306F78118.html
       * IMPORT_C void GetExposureCompensationStepsL(RArray<TInt> &aExposureCompensationSteps, TValueInfo &aInfo) const 
       * aShutterSpeeds a reference to an RArray of TInt representing the discrete shutter speeds supported currently by the camera.
       * aInfo  a reference to TValueInfo, which establishes the type of the returned data. 
       * Returns: the populated array with all shutter speeds in microseconds.
      */ 
      RArray<TInt> exposureCompensationSteps;
      TValueInfo exposureCompensationStepsInfo;
      iAdvancedSettings->GetShutterSpeedsL(exposureCompensationSteps, exposureCompensationStepsInfo);
      TInt lenExposureCompensationSteps = exposureCompensationSteps.Count();
      logf("CMisoPhotoTaker::SetCameraSettingsL(): lenExposureCompensationSteps = %d.", lenExposureCompensationSteps);
      for (index = 0; index < lenExposureCompensationSteps; index++)
          logf("    exposureCompensationSteps[%d] = %d", index, exposureCompensationSteps[index]);
      exposureCompensationSteps.Close();

        /*
         * SupportedFocusRanges()        
         * IMPORT_C TInt SupportedFocusRanges() const
         * Gets all supported focus ranges on the camera.
         * Note: if CCamera::New2L() or CCamera::NewDuplicate2L() is not used to create CCamera object, it is assumed that application is not prepared to receive extra added enum values. So, any extra enum value passed from the implementation will be filtered at this point. To receive extra added enum values, application should rather use CCamera::New2L() or CCamera::NewDuplicate2L() to create camera object. In this case, application is assumed to be prepared to receive unrecognised enum values
         * Returns: an integer - a bitfield of all supported TFocusRange values.
         */
      TInt supportedFocusRanges = iAdvancedSettings->SupportedFocusRanges();
      logf("CMisoPhotoTaker::SetCameraSettingsL(): supportedFocusRanges = %d.", supportedFocusRanges);

      /*
       * IMPORT_C void GetAperturesL(RArray<TInt> &aFStops, TValueInfo &aInfo) const
       * Gets the current discrete aperture steps (F-stops) supported by the camera.
       * leave    KErrNoMemory Out of memory.
       * Note:
       * When camera device is incapable of revealing the aperture openings supported, it has to be assumed that camera will work only on the parmanently set value. If this value is not known, empty array may be returned and TValueInfo may be ENotActive; corresponding getter/setters for this feature should not be used in such a case.
       * Parameter Description
       *   aFStops - A reference to an empty array of TInt which would be populated by the implementation with the specific supported values. If the array is empty on return, the camera supports all integer values in the aperture range. Each value is multiplied by a factor of KECamFineResolutionFactor.
       *   aInfo - a reference to TValueInfo, which establishes the type of the returned data. 
       */
      RArray<TInt> apertures;
      TValueInfo aperturesInfo;
      iAdvancedSettings->GetAperturesL(apertures, aperturesInfo);
      TInt lenApertures = apertures.Count();
      logf("CMisoPhotoTaker::SetCameraSettingsL(): lenApertures = %d.", lenApertures);
      for (index = 0; index < lenApertures; index++)
          logf("    apertures[%d] = %d", index, apertures[index]);
      apertures.Close();

      /*
      IMPORT_C TInt IsoRate() const; - current ISO rate as a TInt value. Negative value returned means error case (system wide error code) and positive value means current ISO rate. 
      */
      
      /*
       * From http://library.forum.nokia.com/index.jsp?topic=/GUID-E35887BB-7E58-438C-AA27-97B2CDE7E069/GUID-251A35C1-CC66-4DE4-9EBE-964026E89E7F/GUID-E31AEB11-B7A0-3637-BB31-866306F78118.html:
       * 
       * IMPORT_C void SetISORateL(TISORateType aISORateType, TInt aParam)
       * 
       * aISORateType   The type of ISO rate to be set. 
       * aParam Depending on the value of aISORateType, possible values of aParam are one of the following...
       * leave
       * KErrNotSupported if the implementation of this method is not present.
       * Note:
       * Triggers KUidECamEventCameraSettingIsoRateType to all MCameraObserver2 clients of the camera. HandleEvent is used to report the result or any possible error. New setter functions leave only when implementation is not there.
       */
      
      /*
       * 
       * IMPORT_C void SetIsoRate(TInt aRate)   
       * Set current ISO rate for the camera. Triggers KUidECamEventCameraSettingIsoRate to all MCameraObserver2 clients of the camera.
       * aRate  required new ISO rate. 
       */
      if (ISORate != -100)  
          iAdvancedSettings->SetIsoRate(ISORate);
        
        /*
         * IMPORT_C void SetShutterSpeed(TInt aShutterSpeed)    
         * Sets the current shutter speed. When set, all MCameraObserver2 clients of the camera receive a KUidECamEventCameraSettingShutterSpeed event
         * Parameter DescriptionaShutterSpeed the required shutter speed in microseconds. 
         */

        /*
         * SetExposureCompensation(TInt)
         * IMPORT_C void SetExposureCompensation(TInt aExposureCompensationInSteps) 
         * Set the current exposure compensation value as integer steps. Triggers a KUidECamEventCameraSettingExposureCompensation event to all MCameraObserver2 clients.
         * Parameter    DescriptionaExposureCompensationInSteps a required number of compensation steps - negative value reduce the exposure time positive increases the exposure time. 
         */
        
        /*
         * SetExposureCompensationStep(TInt)
         * IMPORT_C void SetExposureCompensationStep(TInt aExposureCompensationStep)
         * Set current exposure compensation step as an integer multiplied by KECamFineResolutionFactor. All MCameraObserver2 clients receive a KUidECamEventCameraSettingExposureCompensationStep event, when the value has changed. 
         * Parameter Descriptiona: ExposureCompensationStep - a new value for the exposure compensation step.   
         */
            
        /*
         * IMPORT_C TInt Aperture() const
         * Get current aperture value. The default aperture value is ECAM implementation specific and could be either auto aperture or any other supported value.
         * Returns: Current aperture value as an integer, multiplied by KECamFineResolutionFactor. For example the function will return 280 for the actual aperture of F2.8. Negative value returned means error case (system wide error code) and positive value means current aperture.
         */

         
      /*
        exposure Compensation
        ExposureCompensation()
        ExposureCompensationStep()
        ExposureMode()
        GetExposureCompensationRangeInSteps(), 
        GetExposureCompensationStepsL(), 
        GetFlashCompensationRangeInSteps(), 
        GetFlashCompensationStepsL(), 
        GetManualFlashPowerLevelsL(), 
        GetMinFocalLength(), 
        GetOpticalZoomStepsL(), 
        GetShutterSpeedsL()
    
        Aperture(), 
        ApertureExposureLockOn(), 
        AutoFocusArea(), 
        AutoFocusLockOn(), 
        AutoFocusType(), 
        AutomaticSizeSelectionChangeOn(), 
        BracketMode(), 
        BracketParameter(), 
        BracketParameterAperture, 
        BracketParameterAutoFocus, 
        BracketStep(), 
        BurstImages(), 
        CameraIndex(), 
        CameraType(), 
        CameraType(), 
        ContinuousAutoFocusTimeout(), 
        DigitalZoom(), 
        DriveMode(), 

        ExposureCompensation(), 
        ExposureCompensationStep(), 
        ExposureLockOn(), 
        ExposureMode(), 
        FlashCompensation(), 
        FlashCompensationStep(), 
        FlashMode(), 
        FocusDistance(), 
        FocusMode(), 
        FocusRange(), 
        GetActiveSettingsL(), 
        GetAperturesL(), 
        GetBracketMerge(), 
        GetCurrentFocusModeStepsL(), 
        GetDigitalZoomStepsL(), 
        GetDisabledSettingsL(), 
        GetExposureCompensationRangeInSteps(), 
        GetExposureCompensationStepsL(), 
        GetFlashCompensationRangeInSteps(), 
        GetFlashCompensationStepsL(), 
        GetManualFlashPowerLevelsL(), 
        GetMinFocalLength(), 
        GetOpticalZoomStepsL(), 
        GetShutterSpeedsL(), 
        GetSupportedContinuousAutoFocusTimeoutsL(), 
        GetSupportedIsoRatesL(), 
        GetSupportedSettingsL(), 
        GetTimeLapse(), GetTimeLapsePeriodRange(), GetTimerIntervalsL(), GetWBRgbValue(), GetWBSupportedColorTemperaturesL(), IsCameraPresent(), IsCameraPresent(), IsExternalFlashPresent(), IsFlashReady(), IsoRate(), ManualFlashPowerLevel(), MeteringMode(), NewL(), OpticalZoom(), PictureOrientation(), PixelAspectRatio(), RedEyeReduceOn(), SetAperture(), SetApertureExposureLockOn(), SetAutoFocusArea(), SetAutoFocusLockOn(), SetAutoFocusType(), SetAutomaticSizeSelectionChangeOn(), SetBracketMerge(), SetBracketMode(), SetBracketParameter(), SetBracketStep(), SetBurstImages(), SetContinuousAutoFocusTimeout(), SetDigitalZoom(), SetDriveMode(), SetExposureCompensation(), SetExposureCompensationStep(), SetExposureLockOn(), SetExposureMode(), SetFlashCompensation(), SetFlashCompensationStep(), SetFlashMode(), SetFocusDistance(), SetFocusMode(), SetFocusRange(), SetIsoRate(), SetManualFlashPowerLevel(), SetMeteringMode(), SetOpticalZoom(), SetPictureOrientation(), SetPixelAspectRatio(), SetRedEyeReduceOn(), SetShootClickOn(), SetShutterSpeed(), SetStabilizationComplexity(), SetStabilizationEffect(), SetStabilizationMode(), SetTimeLapse(), SetTimerInterval(), SetWBColorTemperature(), SetWBRgbValue(), SetWhiteBalanceMode(), SetYuvRange(), ShootClickOn(), ShutterSpeed(), StabilizationComplexity(), StabilizationEffect(), StabilizationMode(), SupportedAutoFocusAreas(), SupportedAutoFocusTypes(), SupportedBracketModes(), SupportedBracketParameters(), SupportedBracketSteps(), SupportedDriveModes(), SupportedExposureModes(), SupportedFlashModes(), SupportedFocusModes(), SupportedFocusRanges(), SupportedMeteringModes(), SupportedPixelAspectRatios(), SupportedStabilizationComplexityValues(), SupportedStabilizationEffects(), SupportedStabilizationModes(), SupportedWBUnits(), SupportedWhiteBalanceModes(), SupportedYuvRanges(), TAutoFocusArea, TAutoFocusType, TBracketMode, TBracketParameter, TBracketStep, TCameraType, TDriveMode, TFocusMode, TFocusRange, TMeteringMode, TPictureOrientation, TPixelAspectRatio, TStabilizationAlgorithmComplexity, TStabilizationEffect, TStabilizationMode, TWBUnits, TYuvRange, TimerInterval(), WBColorTemperature(), WhiteBalanceMode(), YuvRange(), ~CCameraAdvancedSettings()
        
      focus
      */
      
      //CCamera::CCameraAdvancedSettings* settings = NULL;
      //TRAPD( err, settings = CCamera::CCameraAdvancedSettings::NewL( *iCamera ));
      //TRAP( err, settings = CCamera::CCameraAdvancedSettings::NewL( *iCamera ));

      /*
      CCamera::CCameraAdvancedSettings:
      */
  #endif
}

void CMisoPhotoTaker::ReserveComplete(TInt aError) 
{
  logf("CMisoPhotoTaker::ReserveComplete(): aError = %d.", aError);

  if (aError) {
    iStatus = aError;
    iLoop->AsyncStop();
    logf("CMisoPhotoTaker::ReserveComplete(): After iLoop->AsyncStop().");
  } else {
    /* From http://library.developer.nokia.com/index.jsp?topic=/GUID-E35887BB-7E58-438C-AA27-97B2CDE7E069/GUID-251A35C1-CC66-4DE4-9EBE-964026E89E7F/GUID-021C509B-C821-3401-B2F4-DE7F52BB16D4.html:
     * Asynchronous method to switch on camera power.
     * User must have successfully called Reserve() prior to calling this function.
     * Calls MCameraObserver::PowerOnComplete() when power on is complete.
     */
      iCamera->PowerOn();
  }
}

void CMisoPhotoTaker::PowerOnComplete(TInt aError) {
  logf("CMisoPhotoTaker::PowerOnComplete(): aError = %d.", aError);

  if (aError) {
    iStatus = aError;
    iLoop->AsyncStop();
    logf("CMisoPhotoTaker::PowerOnComplete(): After iLoop->AsyncStop().");
  } else {
    if (iTakingPhoto) {
      CapturePhoto();
    } else {
      TInt err = KErrNone;
      TRAP(err, iCamera->StartViewFinderBitmapsL(iViewFinderSize));
      if (err!=KErrNone) {
        iStatus = aError;
        iLoop->AsyncStop();
      }
      iViewFinderStatus = EFinderActive;
      iLoop->AsyncStop();
    }
  }
}

void CMisoPhotoTaker::ViewFinderFrameReady(CFbsBitmap& aFrame)
{
  // copying of bitmap is needed since we pass the ownership on:
  CFbsBitmap* frameCopy = NULL;
  TInt err = KErrNone;

  // CFbsBitmap copying from http://forum.newlc.com/index.php/topic,10093.0.html
  TRAP(err, {
    frameCopy = new (ELeave) CFbsBitmap();
    CleanupStack::PushL(frameCopy);
    frameCopy->Create(aFrame.SizeInPixels(), aFrame.DisplayMode());
    
    CFbsBitmapDevice* fbsDev = CFbsBitmapDevice::NewL(frameCopy);
    CleanupStack::PushL(fbsDev);
    CFbsBitGc* fbsGc = CFbsBitGc::NewL();
    CleanupStack::PushL(fbsGc);
    fbsGc->Activate(fbsDev);
    fbsGc->BitBlt(TPoint(0,0), &aFrame);
    
    CleanupStack::PopAndDestroy(2); // fbsDev, fbsGc
    CleanupStack::Pop(1); // frameCopy
  });
  
  if (err!=KErrNone) {
    return; // TODO what is the best way to report this?
  }
  
  iErrorState = iCallMe.NewViewFinderFrameReady(frameCopy);
}

void CMisoPhotoTaker::ImageReady(CFbsBitmap* aBitmap, HBufC8* aData, 
         TInt aError) 
{
  if (aError) {
    iStatus = aError;
    iLoop->AsyncStop();
  } else {
  
    if (iMode == CCamera::EFormatExif) {
      delete iData;
      iData = aData;
    } else {
      delete iBitMap;
      iBitMap = aBitmap;
    }
    
    iLoop->AsyncStop();
  }
}

void CMisoPhotoTaker::FrameBufferReady(MFrameBuffer* /*aFrameBuffer*/, 
          TInt /*aError*/) {}

// New functions for MCameraObserver2
void CMisoPhotoTaker::HandleEvent(const TECAMEvent& aEvent) {}
void CMisoPhotoTaker::ImageBufferReady(MCameraBuffer& aCameraBuffer, TInt aError) {}
void CMisoPhotoTaker::VideoBufferReady(MCameraBuffer& aCameraBuffer, TInt aError) {}
void CMisoPhotoTaker::ViewFinderReady(MCameraBuffer & aCameraBuffer, TInt aError) {}



////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////

// A helper function for the implementation of callbacks
// from C/C++ code to Python callables (modified from appuifwmodule.cpp)
TInt TPyVidCallBack::VideoCameraEvent(TInt aError, TInt aStatus)
  {
  PyGILState_STATE gstate = PyGILState_Ensure();

  TInt error = KErrNone;

  PyObject* arg = Py_BuildValue("(ii)", aError, aStatus);
  PyObject* rval = PyEval_CallObject(iCb, arg);
  
  Py_DECREF(arg);
  if (!rval) {
    error = KErrPython;
    if (PyErr_Occurred() == PyExc_OSError) {
      PyObject *type, *value, *traceback;
      PyErr_Fetch(&type, &value, &traceback);
      if (PyInt_Check(value))
        error = PyInt_AS_LONG(value);
      Py_XDECREF(type);
      Py_XDECREF(value);
      Py_XDECREF(traceback);
    } else {
      PyErr_Print();
    }
  }
  else
    Py_DECREF(rval);  

  PyGILState_Release(gstate);
  return error;
  }

CVideoCamera* CVideoCamera::NewL()
{
  CVideoCamera* video = new (ELeave) CVideoCamera;
  CleanupStack::PushL(video);
  video->ConstructL();
  CleanupStack::Pop();
  return video;
}

CVideoCamera::CVideoCamera(){;}

void CVideoCamera::ConstructL()
{
  iVideo = CVideoRecorderUtility::NewL(*this);

  ////////////////// Following copied from the Forum Nokia VREX example:

  CMMFControllerPluginSelectionParameters* cSelect =
    CMMFControllerPluginSelectionParameters::NewLC();
  CMMFFormatSelectionParameters* fSelect =
    CMMFFormatSelectionParameters::NewLC();

  cSelect->SetRequiredPlayFormatSupportL(*fSelect);
  cSelect->SetRequiredRecordFormatSupportL(*fSelect);

  RArray<TUid> mediaIds;
  CleanupClosePushL(mediaIds);

  User::LeaveIfError(mediaIds.Append(KUidMediaTypeVideo));

  cSelect->SetMediaIdsL(mediaIds,
    CMMFPluginSelectionParameters::EAllowOtherMediaIds);
  cSelect->SetPreferredSupplierL(KNullDesC,
    CMMFPluginSelectionParameters::EPreferredSupplierPluginsFirstInList);

  RMMFControllerImplInfoArray controllers;
  CleanupResetAndDestroyPushL(controllers);
  cSelect->ListImplementationsL(controllers);

  controllersCount = controllers.Count();
  //controllersCount = -1;
  recordFormatsCount = -1;

  TBool recordingSupported = EFalse;

  // Find the first controller with at least one record format available
  for(TInt i = 0; i < controllers.Count(); ++i)
    {
    RMMFFormatImplInfoArray recordFormats = controllers[i]->RecordFormats();

    if(recordFormats.Count() > 0) {
        recordFormatsCount = recordFormats.Count();
        //Alex: iControllerUid and iFormatUid are used in OpenFileL(). 
        iControllerUid = controllers[i]->Uid();
        iFormatUid = recordFormats[0]->Uid();
        recordingSupported = ETrue;
        break;
      }
    }

  CleanupStack::PopAndDestroy(&controllers);
  CleanupStack::PopAndDestroy(&mediaIds);
  CleanupStack::PopAndDestroy(fSelect);
  CleanupStack::PopAndDestroy(cSelect);

  // Leave if recording is not supported
  if(!recordingSupported) {
    User::Leave(KErrNotSupported);
  }
  ////////////////// End copy from the Forum Nokia VREX example
  
  //Added by AltoRetrato here:
  iSize.iWidth  = 0;
  iSize.iHeight = 0;
  iMode         = 0;
  frameRate     = 15.0;
}

CVideoCamera::~CVideoCamera()
{
  if (iVideo) {
    delete iVideo;
  }
}

void CVideoCamera::SetVideoParameters(TInt sizeX, TInt sizeY, TInt mode, TReal32 aFrameRate, TInt aBitrate, const TDesC8 &aVideoType, TBool anAudioEnabled, TInt aAudioType) {
  iSize.iWidth  = sizeX;
  iSize.iHeight = sizeY;
  iMode         = mode; //!!!!Not used - could be used for PrepareVideoCaptureL() - currently PrepareVideoCaptureL() isn't used.  
  frameRate     = aFrameRate;
  iBitrate      = aBitrate;

  videoType     = aVideoType;
  audioEnabled  = anAudioEnabled;

  audioType     = aAudioType; //KMMFFourCCCodeAAC; //Defined in C:\NokiaQtSDK\Symbian\SDK\epoc32\include\mmf\common\mmffourcc.h.
  //audioType     = KMMFFourCCCodeNULL; //!!!!maybe this is equivalent with KNullDesC8 
}

void CVideoCamera::StartRecordL(//TInt aCameraIndex /*Alex: added aCameraIndex since I want to behave differently for the 2 cameras.*/, 
        TInt aHandle, const TDesC& aFileName) {

    /*
     *From: http://wiki.forum.nokia.com/index.php/TSS000680_-_Getting_a_larger_size_video_recorded_by_CVideoRecorderUtility
     *Video capture in VGA (640x480) at 30 fps is possible in devices that support MPEG-4 Visual Simple Profile Level 4 (e.g. Nokia N93, Nokia N95). Most other S60 3rd Edition devices support as least VSP Level 3, that is, CIF (352x288) resolution at 30 fps. 
     */
      // See also: http://developer.symbian.org/xref/oss/xref/MCL/sf/mw/camerasrv/camcordermmfplugin/mediarecorder/Inc/CCMRSupportedCodecs.h
  
    /*See http://library.forum.nokia.com/index.jsp?topic=/Nokia_Symbian3_Developers_Library/GUID-8A183C79-0EA4-3A4A-B95F-E2F1BF74238D.html
     *    or http://library.forum.nokia.com/index.jsp?topic=/GUID-E35887BB-7E58-438C-AA27-97B2CDE7E069/GUID-251A35C1-CC66-4DE4-9EBE-964026E89E7F/GUID-8A183C79-0EA4-3A4A-B95F-E2F1BF74238D.html.
     * void OpenFileL(const TDesC &aFileName, TInt aCameraHandle, TUid aControllerUid, TUid aVideoFormat, const TDesC8 &aVideoType=KNullDesC8, TFourCC aAudioType=KMMFFourCCCodeNULL);
       *    aControllerUid  The UID of the controller to use for recording.       
     *    aVideoFormat  The UID of the video format to record to.
       *    aVideoType  The descriptor containing the video MIME type.
     *    aAudioType    A four character code representing the encoding to be used for audio data.     
     */
    //_LIT8(KMimeTypeMPEG4VSPL3, "video/mp4v-es; profile-level-id=3");  // MPEG-4 Visual Simple Profile Level 3 //for CIF (352x288) resolution at 30 fps.
    //_LIT8(KMimeTypeMPEG4VSPL4, "video/mp4v-es; profile-level-id=4");  // MPEG-4 Visual Simple Profile Level 4
    
    //!!!!Maybe use KMMFFourCCCodeNULL
    iVideo->OpenFileL(aFileName, aHandle, iControllerUid, iFormatUid, videoType, KMMFFourCCCodeAAC);
    /*
    if (camo->myCameraIndex == 1) {
      //For the VGA camera we use the standard videoType, and audioType - otherwise Symbian crashes :o (Original code of camera module):
      iVideo->OpenFileL(aFileName, aHandle, iControllerUid, iFormatUid);
    }
    else {
      iVideo->OpenFileL(aFileName, aHandle, iControllerUid, iFormatUid, videoType, KMMFFourCCCodeAAC);
    }
    */
}

void CVideoCamera::StopRecord()
{
  /* error = */ iVideo->Stop();
  iVideo->Close();
}

void CVideoCamera::SetCallBack(TPyVidCallBack &aCb)  {
  iCallMe = aCb;
  iCallBackSet = ETrue;
}

void CVideoCamera::MvruoEvent(const TMMFEvent &aEvent) {
  // XXX modify the callback as there are not enough parameters
  //     this will not show properly to the Python layer
  if(iCallBackSet)
    iCallMe.VideoCameraEvent(aEvent.iErrorCode, aEvent.iEventType.iUid);
}

void CVideoCamera::MvruoOpenComplete(TInt aError) {
  iCallMe.VideoCameraEvent(aError, CVideoCamera::EOpenComplete);
  if (aError == KErrNone) {
    // XXX err to Python level?
    TRAPD(err, iVideo->SetMaxClipSizeL(KMMFNoMaxClipSize));

    //if (camo->myCameraIndex == 0) {
        //Added by AltoRetrato on top of the original camera module.
        TRAP_IGNORE( iVideo->SetVideoFrameSizeL( iSize ));
        //~ TRAP_IGNORE( iVideo->SetVideoFrameRateL( iFps ));

        //From C:\NokiaQtSDK\Symbian\SDK\epoc32\include\mmf\common\mmfvideo.h: const TInt KMMFVariableVideoBitRate = -1;
        /*
        if (iBitrate == 0)
             { TRAP_IGNORE( iVideo->SetVideoBitRateL( KMMFVariableVideoBitRate ));} // New! This captures only at 15fps!
        else { TRAP_IGNORE( iVideo->SetVideoBitRateL( iBitrate ));}     // New!
        */

        /*From http://library.forum.nokia.com/index.jsp?topic=/GUID-E35887BB-7E58-438C-AA27-97B2CDE7E069/GUID-251A35C1-CC66-4DE4-9EBE-964026E89E7F/GUID-8A183C79-0EA4-3A4A-B95F-E2F1BF74238D.html:
         * IMPORT_C void SetVideoBitRateL(TInt aBitRate)    
         * Parameter: DescriptionaBitRate - The video bit rate in bits/second. This can be called with the parameter KMMFVariableVideoBitRate which specifies a variable bit rate. 
         */
        TRAP_IGNORE( iVideo->SetVideoBitRateL( iBitrate ));
        
        //IMPORT_C void SetVideoFrameRateL(TReal32 aFrameRate);
        TRAP_IGNORE( iVideo->SetVideoFrameRateL( frameRate ) );
        
        //Sets whether the current clip has an audio stream.
        TRAP_IGNORE( iVideo->SetAudioEnabledL(audioEnabled) );

        /*
        From http://library.forum.nokia.com/index.jsp?topic=/S60_3rd_Edition_Cpp_Developers_Library/GUID-35228542-8C95-4849-A73F-2B4F082F0C44/html/SDL_93/doc_source/reference/reference-cpp/MMF/CVideoRecorderUtilityClass.html
          SetGainL()
          GainL()
          GetSupportedVideoTypesL()
          GetSupportedAudioTypesL()
          SetAudioBitRateL()
          SetAudioTypeL()
          AudioBitRateL()
          RecordTimeAvailable()

        methods CVideoRecorderUtility (*iVideo)
        # SetAudioBitRateL(TInt)Sets the audio bit rate.
        # SetAudioChannelsL(const TUint)Sets the number of audio channels to record (1 for mono, 2 for stereo). The clie...
        # SetAudioEnabledL(TBool)Sets whether the current clip has an audio stream.
        # SetAudioSampleRateL(const TUint)Sets the sample rate for audio recording. The client must select the audio codec...
        # SetAudioTypeL(TFourCC)Sets the audio type. This represents the encoding of the audio data within the c...
        # SetGainL(TInt)Sets the audio recording gain.
        # SetMaxClipSizeL(TInt)Sets the maximum recording size for a video clip in bytes.
        # SetPixelAspectRatioL(const TVideoAspectRatio &)Sets recorded video pixel aspect ratio. The client must select the video codec a...
        # SetPriorityL(TInt,TMdaPriorityPreference)Sets the recording priority. This is used to arbitrate between simultaneous acce...
        # SetVideoTypeL(const TDesC8 &)Sets the codec to use for the video component of the video clip.
        **
        # GetPixelAspectRatioL(TVideoAspectRatio &)constGets the current pixel aspect ratio.
        # GetPriorityL(TInt &,TMdaPriorityPreference &)constGets the current recording priority. This is used to arbitrate between simultane...
        # GetSupportedAudioChannelsL(RArray< TUint > &)constGets the list of the supported numbers of audio channels. One channel represents...
        # GetSupportedAudioSampleRatesL(RArray< TUint > &)constGets the list of the supported audio sample rates. The client must select the au...
        # GetSupportedAudioTypesL(RArray< TFourCC > &)constGets a list of the audio types that are supported for recording to.
        # GetSupportedPixelAspectRatiosL(RArray< TVideoAspectRatio > &)constGets a list of supported pixel aspect ratios. The client must select the video c...
        # !!!!GetSupportedVideoTypesL(CDesC8Array &)constGets a list of the video types that are supported for recording to.
        # GetVideoFrameSizeL(TSize &)constGets the video frame size.
        */
      //}

    if(err==KErrNone) {
        /* From http://discussion.forum.nokia.com/forum/showthread.php?210411-How-to-record-HD-video-on-Nokia-N8:
          "To enable the settings you have set after OpenFileL() you need to call Prepare();
           Try adding iVideo->Prepare(); and wait for the corresponding callback and then start recording." 
           Alex: Note: The corresponding callback is MvruoPrepareComplete.  
        */
        iVideo->Prepare();
    }
  }
}

void CVideoCamera::MvruoPrepareComplete(TInt aError) {
  iCallMe.VideoCameraEvent(aError, CVideoCamera::EPrepareComplete);
  if (aError==KErrNone) {
    //Alex
    //From http://library.forum.nokia.com/index.jsp?topic=/S60_5th_Edition_Cpp_Developers_Library/GUID-35228542-8C95-4849-A73F-2B4F082F0C44/sdk/doc_source/reference/reference-cpp/Multimedia_Framework/CVideoRecorderUtilityClass.html
    //"This function must not be called until a MVideoRecorderUtilityObserver::MvruoPrepareComplete(TInt) has been received with an aError equal to KErrNone. "
    iVideo->Record();
  }
}

void CVideoCamera::MvruoRecordComplete(TInt aError) {
  iCallMe.VideoCameraEvent(aError, CVideoCamera::ERecordComplete);
}



/*
#ifdef USE_NEW_CAMERA_API
void CFastCamera::ViewFinderReady(MCameraBuffer& aCameraBuffer, TInt aError) {
    LOG(_L("CFastCamera::ViewFinderReady"));
    if (aError == KErrNone)
    {
        ViewFinderFrameReady(aCameraBuffer.BitmapL(0));
        aCameraBuffer.Release();
    }
    else {
        LOG(_L("Error copying viewfinder frame"));
    }  
}

void CFastCamera::ImageBufferReady(MCameraBuffer& aCameraBuffer, TInt aError) {
    LOG(_L("CFastCamera::ImageBufferReady"));
    if( aError == KErrNone )
    {
        if (iMode == CCamera::EFormatExif || iMode == CCamera::EFormatJpeg) {
            TRAPD(ignore, InternalImageReady(NULL, aCameraBuffer.DataL(0), aError, EFalse)); 
        }
        else {
            // copying of bitmap is needed since we pass the ownership on:
            CFbsBitmap* frameCopy = NULL;
        
            TRAPD(err, 
                frameCopy = CopyBitmapL(aCameraBuffer.BitmapL(0));
            );
            if (err != KErrNone) aError = err;
            TRAPD(ignore, InternalImageReady(frameCopy, NULL, aError, EFalse)); 
        }
    }
    else {
        InternalImageReady(NULL, NULL, aError, EFalse); 
    }
  
    aCameraBuffer.Release();
    LOG(_L("CFastCamera::ImageBufferReady done"));
}
void CFastCamera::VideoBufferReady(MCameraBuffer& aCameraBuffer, TInt aError) {}

void CFastCamera::HandleEvent(const TECAMEvent &aEvent) {
    LOG(_L("CFastCamera::HandleEvent"));
    if( aEvent.iEventType == KUidECamEventReserveComplete )
    {
        ReserveComplete(aEvent.iErrorCode);
        return;
    }
      
    if( aEvent.iEventType == KUidECamEventPowerOnComplete )
    {       
        PowerOnComplete(aEvent.iErrorCode);
        return;
    }
   // AUTOFOCUS RELATED EVENTS
  switch(aEvent.iEventType.iUid)
      {
      // Set some basic settings automatically (AF Area, Focus Range)
      // after receiving a call to SetFocusMode()
      case KUidECamEventCameraSettingFocusModeUidValue:
          {
              if ( KErrNone == aEvent.iErrorCode )
              {
                // don't have to check useNewFocus, if we're here then it's new
                iCameraAdvancedSettings->SetAutoFocusArea(CCamera::CCameraAdvancedSettings::EAutoFocusTypeAuto);
              }
              else
              {
                    // init failed
                    DoFocusCallback(0, aEvent.iErrorCode);
              }
              break;
          }

      case KUidECamEventCameraSettingAutoFocusAreaUidValue:
          {
              if ( !aEvent.iErrorCode )
              {
                    // don't have to check useNewFocus, if we're here then it's new
                    iCameraAdvancedSettings->SetFocusRange(CCamera::CCameraAdvancedSettings::EFocusRangeNormal);              
              }
              else
              {
                    // init failed
                    DoFocusCallback(0, aEvent.iErrorCode);
              } 
              break;
          }
          
      case KUidECamEventCameraSettingFocusRange2UidValue:
          {
                // init done (or failed)
                DoFocusCallback(0, aEvent.iErrorCode);
                break;
          }
          
      // Optimal focus has been attained
      case KUidECamEventCameraSettingsOptimalFocusUidValue:
            DoFocusCallback(1, aEvent.iErrorCode);
            break;
          
      default:
          break;
      }
}
#endif


//Sets the viewfinder mirror
static PyObject * cam_setviewfindermirror(CAM_object* self, PyObject *args)
{
    TInt viewfindermirror;
    
    if (!PyArg_ParseTuple(args, "i", &viewfindermirror))
        return NULL;
    
    TRAPD(err, self->camera->SetViewFinderMirrorL(viewfindermirror != 0));
  
    return Py_BuildValue("i", err);
}

//Returns the viewfinder mirror
static PyObject *cam_viewfindermirror(CAM_object* self, PyObject ) //args)
{
    return Py_BuildValue("i", self->camera->ViewFinderMirror());
}

//Sets the zoom
static PyObject * cam_setzoom(CAM_object* self, PyObject *args)
{
    TInt zoom;
    
    if (!PyArg_ParseTuple(args, "i", &zoom))
        return NULL;
    
    TRAPD(err, self->camera->SetZoomL(zoom));
  
    return Py_BuildValue("i", err);
}

void CFastCamera::EnsureFocus() {
    LOG(_L("EnsureFocus"));
    // try to construct the autofocus class
    TInt err = 0;
    #ifdef USE_NEW_CAMERA_API
    if (useNewFocus) {
        if (iCameraAdvancedSettings == NULL) {
            TRAP(err, iCameraAdvancedSettings = CCamera::CCameraAdvancedSettings::NewL(*iCamera));
        }
    }
    else {
        if (iCamAutoFocus == NULL) {
            TRAP(err, iCamAutoFocus = CCamAutoFocus::NewL(iCamera));
        }
    }
    #else
    if (iCamAutoFocus == NULL) {
        TRAP(err, iCamAutoFocus = CCamAutoFocus::NewL(iCamera));
    }
    #endif
    if (!err) {
        TRAP(err, InitL());
    }
    if (err) {
        Unsupported(err);

        // send error code
        LOG(_L("focus callback"));
        DoFocusCallback(0, err);
        LOG(_L("focus callback done"));
    }
    LOG(_L("CFastCamera.EnsureFocus done"));
}

#ifdef USE_NEW_CAMERA_API
        // MCameraObserver2
        void HandleEvent(const TECAMEvent &aEvent);
        void ViewFinderReady(MCameraBuffer &aCameraBuffer, TInt aError);
        void ImageBufferReady(MCameraBuffer &aCameraBuffer, TInt aError);
        void VideoBufferReady(MCameraBuffer& aCameraBuffer, TInt aError);
#endif





From AltoRetrato
    take_photo
      TInt focusr= CCamera::CCameraAdvancedSettings::EFocusRangeInfinite; // New!

    Constants registered:
        // Focus Range - New!
        PyDict_SetItemString(d,"ERangeMacro", PyInt_FromLong(1));
        PyDict_SetItemString(d,"ERangePortrait", PyInt_FromLong(2));
        PyDict_SetItemString(d,"ERangeNormal", PyInt_FromLong(4));
        PyDict_SetItemString(d,"ERangeInfinite", PyInt_FromLong(8));    

    void CMisoPhotoTaker::TakePhotoL(TInt aMode, TInt aSize, 
                                            TInt aZoom, TInt aFlash, 
                                            TInt aExp, TInt aWhite, TInt aFocusRange)
      iFocusRange = static_cast<CCamera::CCameraAdvancedSettings::TFocusRange>(aFocusRange); // New!

    void CMisoPhotoTaker::SetSettingsL()
      SetFocusRange(iFocusRange); // New!

    TInt CMisoPhotoTaker::SetFocusRange(CCamera::CCameraAdvancedSettings::TFocusRange focusRange) { // New!
       CCamera::CCameraAdvancedSettings* settings = NULL;
       TRAPD( err, settings = CCamera::CCameraAdvancedSettings::NewL( *iCamera ));
       if ( err || !settings)
          return -1;

       // Gets the supported ranges            
       TInt suppRanges = settings->SupportedFocusRanges();
        
       // Checks if the focus range is supported before setting it.
       if (focusRange & suppRanges)  {
          // Sets the focus range if it is supported
          settings->SetFocusRange(focusRange);
          return 1;
       }
       return 0;
    }


*/
